<?php
/**
 * TypeFactory for creating new EDO types
 *
 * @package EDO
 * @subpackage typeFactory
 */
class TypeFactory
{
	protected $ldb;
	
	public function __construct(LDB_base $ldb)
	{
		$this->ldb = $ldb;
	}
	
	public static function connect(LDB_base $ldb)
	{
		static $connections;
		
				
		if(isset($connections[$ldb->dsn]))
		{
			return $connections[$ldb->dsn];
		}
				
						

		$handler = new TypeFactory($ldb);
		$connections[$ldb->dsn] = $handler;
		return $handler;
	}
	
	/**
	 * Creates new edo types
	 *
	 * @param string $className
	 * @param bool $isDynamic
	 * @param integer $typeId
	 * @return integer typeid of the created type
	 * @throws Exception on failure
	 */
	public function createObject($className, $isDynamic = true, $typeId = null)
	{
		if(is_string($className) && strlen($className < 100))
		{
			$isDynamic = ($isDynamic)?1:0;
			$typeId = ($typeId && is_int($typeId))?$typeId:$this->getNewTypeId();
			$arrObject = array(	'classname' => $className,
								'typeid' => $typeId,
								'dynamic' => $isDynamic
								);
			if(!$this->ldb->autoExecute('edo_types', $arrObject, LDB::AUTOQUERY_INSERT))
			{
				throw new Exception('Could not create new object type, might exist');
			}
			return $typeId;
		}else throw new Exception('Invalid classname');
	}
	
	/**
	 * getNewTypeId returns a new type id
	 * 
	 * @todo create sequence, or something. Now just selects MAX+1.
	 *
	 */
	private function getNewTypeId()
	{
		$sql = "SELECT MAX(typeid) FROM edo_types";
		$typeid = $this->ldb->getOne($sql);
		if(!$typeid && $typeid !== 0) // zero is accepted since were going to inc it
		{
			throw new Exception('No valid typeid recieved');
		}
		return $typeid + 1;
	}
	
	/**
	 * deleteType deletes an existing edo type from db
	 * 
	 * Deleting an existing type should check: 
	 * 
	 * 1) if there are relations to that type
	 * 2) if there are objects of that type
	 * 
	 * @param integer $typeid
	 * @param boolean $deleteExisting, Default: false
	 * @return boolean
	 */
	public function deleteType($typename, $deleteExisting = false)
	{
	    $typeid = $this->ldb->getOne("SELECT typeid FROM edo_types WHERE classname='{$typename}'");
		if($typename)
		{
			// checks if there are any relations to this type
			$arrRelated = $this->getRelations($typeid);
	
			
			if($arrRelated)
			{
			    $e = new EDO_RelationsExistException('Relations exist');
				$e->setRelations($arrRelated);
				throw $e;
			}
			
			// check if objects of the deleted type exist
			$arrObjects = $this->getObjects($typeid);
			if($arrObjects)
			{
				if(!$deleteExisting)
				{
					$e = new EDO_ObjectsExistException('Objects exist');
					$e->setObjects($arrObjects);
					throw $e;
				}

			}
			
			$edo = EDO::connect($this->ldb);
			$oDelete = $edo->get($typename);	
			$arrTbl = $oDelete->getTables();
            if(sizeof($arrTbl))			
            {
                $e = new EDO_RelationsExistException('Tables exist');
                throw $e;
            }
			
			#die("***".__FILE__);
					
			$this->ldb->query("DELETE FROM edo_types WHERE typeid={$typeid}");
			#print_r($this->ldb->errorInfo());die();
			return true;
		}
		return false;
	}
	
	/**
	 * Returns a list of typeids who have relations to given typename
	 *
	 * @param string $typename
	 * @return Array
	 */
	private function getRelations($typeid)
	{
		$relations = $this->ldb->getOne("SELECT COUNT(typeid) as roo FROM edo_dynamic_relation WHERE typeid = {$typeid}");
		return $relations;
	}
	
	private function getObjects($typeid)
	{
		$objects = $this->ldb->getOne("SELECT edoid FROM edo_objects WHERE typeid = {$typeid}");
		return $objects;
	}
}